package a2_p04_ak_fh;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

import org.jgrapht.Graph;
import org.jgrapht.WeightedGraph;
import org.jgrapht.graph.DirectedWeightedMultigraph;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.WeightedMultigraph;

public class IOHelper {

	/**
	 * readGraphFile
	 * 
	 * @param filePath
	 *            - Path to GraphFile
	 * @return Graph from file
	 */
	public WeightedGraph<AttVertex, DefaultWeightedEdge> readGraphFile(String filePath) {

		boolean gerichtet = false;
		boolean attributiert = false;
		boolean gewichtet = false;

		WeightedGraph<AttVertex, DefaultWeightedEdge> graph = null;

		try {
			FileInputStream fstream = new FileInputStream(filePath);
			// Get the object of DataInputStream
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;
			// Read File Line By Line

			while ((strLine = br.readLine()) != null
					&& strLine.startsWith("#", 0)) {
				if (strLine.contains("gerichtet")
						&& !strLine.contains("ungerichtet")) {
					gerichtet = true;
				}
				if (strLine.contains("gewichtet")) {
					gewichtet = true;
				}
				if (strLine.contains("attributiert")) {
					attributiert = true;
				}
				// Mark Stream
				br.mark(50);
			}

			if (gerichtet) {

				graph = new DirectedWeightedMultigraph<AttVertex, DefaultWeightedEdge>(
						DefaultWeightedEdge.class);
			} else {

				graph = new WeightedMultigraph<AttVertex, DefaultWeightedEdge>(
						DefaultWeightedEdge.class);
			}

			// Reset Reader to end of last attribute line
			br.reset();

			// Create graph from File
			if (attributiert && gewichtet) {

				while ((strLine = br.readLine()) != null) {
					String[] splitted = strLine.split(",");
					// Add vertices
			
						
					AttVertex v1 = new AttVertex(splitted[0],
							Double.parseDouble(splitted[1]));
					AttVertex v2 = new AttVertex(splitted[2],
							Double.parseDouble(splitted[3]));
					graph.addVertex(v1);
					graph.addVertex(v2);

					// Add edge
					DefaultWeightedEdge edge = new DefaultWeightedEdge();

					// Add Weight
					edge = graph.addEdge(v1, v2);
					graph.setEdgeWeight(edge, Double.parseDouble(splitted[4]));
					
					
				}

			} else if (attributiert) {
				while ((strLine = br.readLine()) != null) {
					String[] splitted = strLine.split(",");
					// Add vertices
					AttVertex v1 = new AttVertex(splitted[0],
							Double.parseDouble(splitted[1]));
					AttVertex v2 = new AttVertex(splitted[2],
							Double.parseDouble(splitted[3]));
					graph.addVertex(v1);
					graph.addVertex(v2);

					// Add edge
					graph.addEdge(v1, v2);
				}

			} else if (gewichtet) {
				while ((strLine = br.readLine()) != null) {
					String[] splitted = strLine.split(",");
					// Add vertices
					AttVertex v1 = new AttVertex(splitted[0], 0);
					AttVertex v2 = new AttVertex(splitted[1], 0);
					graph.addVertex(v1);
					graph.addVertex(v2);

					// Add edge
					DefaultWeightedEdge edge = new DefaultWeightedEdge();

					// Add Weight
					edge = graph.addEdge(v1, v2);
					graph.setEdgeWeight(edge, Double.parseDouble(splitted[2]));
				}

			} else {
				while ((strLine = br.readLine()) != null) {
					String[] splitted = strLine.split(",");

					// Add vertices
					AttVertex v1 = new AttVertex(splitted[0], 0);
					AttVertex v2 = new AttVertex(splitted[1], 0);
					graph.addVertex(v1);
					graph.addVertex(v2);

					// Add edge
					graph.addEdge(v1, v2);
				}

			}

			// Close the input stream
			in.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}
		return graph;
	}

	/**
	 * writeGraphFile
	 * 
	 * @param graph
	 *            - Graph to write in file
	 * @param filePath
	 *            - Path to put file to
	 */
	public void writeGraphFile(Graph<AttVertex, DefaultWeightedEdge> g, String filePath, boolean attributed, boolean weighted) {
		try {
			// Open File Streams
			FileOutputStream fstream = new FileOutputStream(filePath);
			DataOutputStream out = new DataOutputStream(fstream);
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
			
			// Check if Graph is directed or undirected
			if (g instanceof DirectedWeightedMultigraph) {
				bw.append("#gerichtet");
				bw.newLine();
			} else if (g instanceof WeightedMultigraph) {
				bw.append("#ungerichtet");
				bw.newLine();
				if(attributed || weighted) {
					if(weighted) {
						bw.append("#gewichtet");
					}
					if(attributed) {
						bw.append("#attributiert");
					}
					bw.newLine();
				}
			}
			// Read graph edges and write them to graphfile
			for (DefaultWeightedEdge edge : g.edgeSet()) {
				bw.append(g.getEdgeSource(edge).getName());
				if(attributed) {
					bw.append(","+g.getEdgeSource(edge).getAttribute().toString());
				}
				bw.append(","+g.getEdgeTarget(edge).getName());
				if(attributed) {
					bw.append(","+g.getEdgeTarget(edge).getAttribute().toString());
				}
				if(weighted) {
					bw.append(","+g.getEdgeWeight(edge));
				}
				bw.newLine();
			}

			// Flush all changes to file
			bw.flush();

			// Close file stram
			out.close();

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
